#include <mips/regdef.h>
#include <sys/syscall.h>

	.data
	.align 2

espacio_lectura: 
	.byte 0
conversion_ascii: 
	.word 1,2,4,8,16,32,64,128
char_cero: 
	.ascii "0" 
char_uno: 
	.ascii "1" 

// ----------------------------------------------------------------------------------

	.text
	.align 2
	
	.global encode
	.ent encode

encode:
	.frame 	$fp,40,ra
	.set noreorder
	.cpload t9
	.set reorder

	subu 	sp,sp,40 			#creo el stack frame correspondiente
	.cprestore 24

	sw 		ra,32(sp) 			#almaceno los valores correspondientes al registro fp, gp y ra
	sw 		$fp,28(sp) 		
	sw 		gp,24(sp) 		
	move 	$fp,sp
	sw 		a0,40($fp) 			#guardo el argumento enviado por la funcion main en el stack de la caller

	li 		t0, 7 				#t0 es i = 7
	move 	t1, a0 				#t1 posee el caracter leido que será pasado a binario
	la 		t4, conversion_ascii
	sw 		t4, 20($fp) 		#el inicio del vector utilizado para convertir a ascii

encode_for:
	bltz 	t0, encode_end 		#condición de corte del for
	lw 		t1,40($fp) 			#levanto el char enviado por la función main en t0
	sll 	t3, t0, 2 			#genero la dir a acceder
	lw 		t4, 20($fp) 		#levanto del stack el inicio del vector utilizado para convertir a ascii
	add 	t4,t4,t3
	lw 		t4, 0(t4) 			#t4 lo utilizo para determinar si hay 1 o 0 en el bit de la posicion i correspondiente
	and 	t4, t1, t4 			#almaceno en t4 el resultado del AND entre el char y el bit de la posicion i

	sw 		t0, 16($fp) 		#Guardo el index en memoria antes del syscall

	beqz 	t4, resul_encode_0 	#Si es cero saltamos a la rutina para escribir un 0 en la salida
	bnez 	t4, resul_encode_1 	#Si es uno saltamos a la rutina para escribir un 1 en la salida

resul_encode_0:
	li 		a0, 1 				#salida por stdout
	la 		a1, char_cero 			
	li 		a2, 1 				#escribo un byte
	b 		encode_write 		

resul_encode_1:
	li 		a0, 1 				#salida por stdout
	la 		a1, char_uno 
	li 		a2, 1 				#escribo un byte
	
encode_write:
	li 		v0,SYS_write 		#carga en v0 el codigo correspondiente a la escritura
	syscall
	bne 	a3,zero,encode_error 	#chequea si ocurrio un error en la escritura
	
	lw 		t0, 16($fp) 		#cargo el index de memoria despues del syscall
	addi 	t0, t0, -1 			#Decremento en 1 el contador
	b 		encode_for 			#vuelve al principio del for

encode_error:
	li 		v0, -1 				#coloco el código de error como devolución del encode
	b 		encode_end

encode_end:
	lw 		ra,32($fp) 			#Recupero los registros fp, gp y ra del stack
	lw 		$fp,28($fp) 
	lw 		gp,24($fp) 
	addu 	sp,sp,40
	j 		ra					#vuelvo al main

	.end encode

// ----------------------------------------------------------------------------------

	.global main
	.ent main

main:
	.frame 	$fp,32,ra
	.set noreorder
	.cpload t9
	.set reorder

	subu 	sp,sp,32 			#creo el stack frame correspondiente
	.cprestore 16

	sw 		ra,24(sp) 			#almaceno los valores correspondientes al registro fp, gp y ra
	sw 		$fp,20(sp) 
	sw 		gp,16(sp) 
	move 	$fp,sp
	
	sw 		a0,32($fp) 
	sw 		a1,36($fp) 

	move 	v0, zero 			#inicializo v0 con cero

main_while:
	li 		a0, 0 				#lectura por stdin
	la 		a1, espacio_lectura		#espacio destinado para la lectura
	li 		a2, 1 				#leer solo un byte
	li 		v0,SYS_read
	syscall
	
	bne 	a3,zero,main_end
	
	li 		t0, 1
	bne 	t0,v0,main_end 		#chequeo que haya leido el caracter

	lb 		t0,espacio_lectura(zero) 	#Cargo el caracter leido
	move 	a0, t0 				#Preparo el caracter leido como parámetro de encode
	jal 	encode
	
	li 		t0, -1
	beq 	v0,t0,main_end 		#Sale del programa si hay error
	b 		main_while 			#Loopea hasta que no haya nada mas que leer

main_end:
	lw 		ra,24(sp) 			#Recupero los registros fp, gp y ra del stack
	lw 		$fp,20(sp) 			
	lw 		gp,16(sp) 			
	addu 	sp,sp,32
	j 		ra					#vuelvo el control al llamante
	
	.end main
